package com.css.fxfzxczh.modules.map.service.impl;

import cn.hutool.core.io.FileUtil;
import com.css.fxfzxczh.base.annotation.EntityValue;
import com.css.fxfzxczh.base.attachment.entity.AttachmentInfoEntity;
import com.css.fxfzxczh.base.attachment.service.AttachmentInfoService;
import com.css.fxfzxczh.base.response.RestResponse;
import com.css.fxfzxczh.common.rest.model.bo.GetChinaGridBo;
import com.css.fxfzxczh.constants.FxfzConstants;
import com.css.fxfzxczh.constants.GeomTypeEnum;
import com.css.fxfzxczh.constants.YNEnum;
import com.css.fxfzxczh.modules.buildingKilometerGrid.threadpool.BizThreadPoolManage;
import com.css.fxfzxczh.modules.fastDisasterAnalysis.fastSeismicInfluence.service.IntensityAttenuationService;
import com.css.fxfzxczh.modules.fieldWorkManage.lnvestigationTaskMange.entity.InvestigationTask;
import com.css.fxfzxczh.modules.fieldWorkManage.surTaskManage.entity.SurTaskManage;
import com.css.fxfzxczh.modules.hypergraph.service.HypergraphService;
import com.css.fxfzxczh.modules.largeScreen.vo.IntensityMapVo;
import com.css.fxfzxczh.modules.map.entity.DisasterSeismicInfluence;
import com.css.fxfzxczh.modules.map.entity.DrawSeismicInfluence;
import com.css.fxfzxczh.modules.map.entity.FieldDesc;
import com.css.fxfzxczh.modules.map.entity.SeismicInfluence;
import com.css.fxfzxczh.modules.map.service.ShpDataService;
import com.css.fxfzxczh.modules.synthesizeInfoManage.earEveManage.entity.EarEveManage;
import com.css.fxfzxczh.util.PlatformObjectUtils;
import com.css.fxfzxczh.util.ResponseCreator;
import com.css.fxfzxczh.util.UUIDGenerator;
import com.css.fxfzxczh.util.fileParsing.ParsingResult;
import com.css.fxfzxczh.util.fileParsing.shp.ShpAnalyticUtil;
import com.css.fxfzxczh.web.PlatformSessionContext;
import com.css.fxfzxczh.zcpt.sys.service.SUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Zyt
 * @date 2023年05月25日  10:00
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ShpDataServiceImpl implements ShpDataService {

    @Value("${image.localDir}")
    private String localDir;

    @Resource
    AttachmentInfoService attachmentInfoService;

    @Resource
    SUserService sUserService;

    @Resource
    JdbcTemplate jdbcTemplate;

    @Resource
    NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    @Resource
    HypergraphService hypergraphService;

    @Resource
    IntensityAttenuationService intensityAttenuationService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResponse parseShp(String fileIds, String typeCode) throws Exception{
        if (!shpFileAllHasCheck(fileIds)) {
            return RestResponse.fail("shp,cpg,dbf,prj,shx未全部上传或者正在上传中，请上传完成后再继续!");
        }
//        this.uniformFileName(fileIds);
//        ParsingResult shpData = getShpData(fileIds);
        //统一文件名，提取出临时文件
        Map<String, File> fileMap = this.uniformFileName1(fileIds);
        //解析shp
        ParsingResult shpData = getShpData(fileMap);
        //是否成功
        if (!shpData.getMessage().equals("ok")) {
            return RestResponse.fail(shpData.getMessage());
        }
        return saveShpTemporaryData(shpData,typeCode);
    }

    /**
     * 检查空间文件的完整性
     *
     * @param fileIds
     * @return
     */
    public boolean shpFileAllHasCheck(String fileIds) {
        String[] split = fileIds.split(",");
        Map<String, Boolean> map = new HashMap<>();
        map.put("shp", false);
        map.put("prj", false);
        map.put("dbf", false);
        map.put("cpg", false);
        map.put("shx", false);
        for (String id : split) {
            AttachmentInfoEntity attach = attachmentInfoService.getAttach(id);
            String suffix = FileUtil.getSuffix(attach.getAttachName());
            if (map.get(suffix) != null) {
                map.put(suffix, true);
            }
        }
        for (Boolean value : map.values()) {
            if (!value) {
                return false;
            }
        }
        return true;
    }

    /**
     * 保存解析的数据
     */
    private RestResponse saveShpTemporaryData(ParsingResult shpData,String typeCode){
        try {
            if (!PlatformObjectUtils.isEmpty(typeCode)) {
                if(typeCode.contains(FxfzConstants.ZQFW)){//灾区范围（划定评估子区页面）
                    String xsemId = typeCode.split(",")[1];//当前地震事件id
                    if (!PlatformObjectUtils.isEmpty(xsemId)) {
                        //根据事件ID逻辑删除灾区范围（划定评估子区页面）
                        deleteSeismicInfluence(xsemId);
                        //灾区范围
                        List<SeismicInfluence> resultList = new ArrayList();
                        List<List<Object>> shpList = shpData.getShpList();
                        for (int i = 0; i < shpList.size(); i++) {
                            List<Object> list = shpList.get(i);
                            SeismicInfluence obj = new SeismicInfluence();
                            obj.setGeom(ShpAnalyticUtil.checkGeomTypeOf(list.get(0).toString(), GeomTypeEnum.MULTIPOLYGON));
//                            obj.setArea(BigDecimal.valueOf(ShpAnalyticUtil.getDoubleVal(list.get(4).toString(), "面积", true)));
//                            obj.setIntensity1(ShpAnalyticUtil.getStringVal(list.get(5).toString(), "烈度", true));
//                            obj.setIntensitys(ShpAnalyticUtil.getStringVal(list.get(6).toString(), "烈度", true));
//                            obj.setIntensity(ShpAnalyticUtil.getStringVal(list.get(7).toString(), "烈度", true));
                            obj.setArea(BigDecimal.valueOf(ShpAnalyticUtil.getDoubleVal(list.get(2).toString(), "面积", true)));
                            String intensity1 = ShpAnalyticUtil.getStringVal(list.get(3).toString(), "烈度", false);
                            String intensitys = ShpAnalyticUtil.getStringVal(list.get(4).toString(), "烈度", false);
                            String intensity = ShpAnalyticUtil.getStringVal(list.get(5).toString(), "烈度", true);
                            //罗马数字1-12：1-Ⅰ、2-Ⅱ、3-Ⅲ、4-Ⅳ、5-Ⅴ、6-Ⅵ、7-Ⅶ、8-Ⅷ、9-Ⅸ、10-Ⅹ、11-Ⅺ、12-Ⅻ
                            if(intensity.equals("6")){
                                intensitys = "Ⅵ";
                            }else if(intensity.equals("7")){
                                intensitys = "Ⅶ";
                            }else if(intensity.equals("8")){
                                intensitys = "Ⅷ";
                            }else if(intensity.equals("9")){
                                intensitys = "Ⅸ";
                            }else if(intensity.equals("10")){
                                intensitys = "Ⅹ";
                            }else if(intensity.equals("11")){
                                intensitys = "Ⅺ";
                            }else if(intensity.equals("12")){
                                intensitys = "Ⅻ";
                            }else{
                                //不符合字段要求
                                ShpAnalyticUtil.getStringValDataWarning(intensitys,"烈度");
                            }
                            intensity1 = intensitys + "度（"+intensity+"度）";//VI度(6度)
                            obj.setIntensity1(intensity1);
                            obj.setIntensitys(intensitys);
                            obj.setIntensity(intensity);
                            //用户ID
                            String userID = PlatformSessionContext.getUserID();
                            obj.setSiId(UUIDGenerator.getUUID());
                            obj.setXsemId(xsemId);//事件ID
                            obj.setCreateTime(new Date());
                            obj.setCreateUser(userID);
                            obj.setDelFlag(YNEnum.N.toString());
                            resultList.add(obj);
                            //保存灾区范围（划定评估子区页面）
                            saveSeismicInfluence(obj);
                        }

                        return RestResponse.succeed(resultList);
                    }
                }else if(typeCode.contains(FxfzConstants.DSTA)){//灾区范围（灾区范围页面）
                    String xsemId = typeCode.split(",")[1];//当前地震事件id
                    if (!PlatformObjectUtils.isEmpty(xsemId)) {
                        //根据事件ID逻辑删除灾区范围（灾区范围页面）
                        deleteDisasterSeismicInfluence(xsemId);
                        //灾区范围
                        List<DisasterSeismicInfluence> resultList = new ArrayList();
                        List<List<Object>> shpList = shpData.getShpList();
                        for (int i = 0; i < shpList.size(); i++) {
                            List<Object> list = shpList.get(i);
                            DisasterSeismicInfluence obj = new DisasterSeismicInfluence();
                            obj.setGeom(ShpAnalyticUtil.checkGeomTypeOf(list.get(0).toString(), GeomTypeEnum.MULTIPOLYGON));
//                            obj.setArea(BigDecimal.valueOf(ShpAnalyticUtil.getDoubleVal(list.get(4).toString(), "面积", true)));
//                            obj.setIntensity1(ShpAnalyticUtil.getStringVal(list.get(5).toString(), "烈度", true));
//                            obj.setIntensitys(ShpAnalyticUtil.getStringVal(list.get(6).toString(), "烈度", true));
//                            obj.setIntensity(ShpAnalyticUtil.getStringVal(list.get(7).toString(), "烈度", true));
                            obj.setArea(BigDecimal.valueOf(ShpAnalyticUtil.getDoubleVal(list.get(2).toString(), "面积", true)));
                            String intensity1 = ShpAnalyticUtil.getStringVal(list.get(3).toString(), "烈度", false);
                            String intensitys = ShpAnalyticUtil.getStringVal(list.get(4).toString(), "烈度", false);
                            String intensity = ShpAnalyticUtil.getStringVal(list.get(5).toString(), "烈度", true);
                            //罗马数字1-12：1-Ⅰ、2-Ⅱ、3-Ⅲ、4-Ⅳ、5-Ⅴ、6-Ⅵ、7-Ⅶ、8-Ⅷ、9-Ⅸ、10-Ⅹ、11-Ⅺ、12-Ⅻ
                            if(intensity.equals("6")){
                                intensitys = "Ⅵ";
                            }else if(intensity.equals("7")){
                                intensitys = "Ⅶ";
                            }else if(intensity.equals("8")){
                                intensitys = "Ⅷ";
                            }else if(intensity.equals("9")){
                                intensitys = "Ⅸ";
                            }else if(intensity.equals("10")){
                                intensitys = "Ⅹ";
                            }else if(intensity.equals("11")){
                                intensitys = "Ⅺ";
                            }else if(intensity.equals("12")){
                                intensitys = "Ⅻ";
                            }else{
                                //不符合字段要求
                                ShpAnalyticUtil.getStringValDataWarning(intensitys,"烈度");
                            }
                            intensity1 = intensitys + "度（"+intensity+"度）";//VI度(6度)
                            obj.setIntensity1(intensity1);
                            obj.setIntensitys(intensitys);
                            obj.setIntensity(intensity);
                            //用户ID
                            String userID = PlatformSessionContext.getUserID();
                            obj.setSiId(UUIDGenerator.getUUID());
                            obj.setXsemId(xsemId);//事件ID
                            obj.setCreateTime(new Date());
                            obj.setCreateUser(userID);
                            obj.setDelFlag(YNEnum.N.toString());
                            resultList.add(obj);
                            //保存灾区范围（灾区范围页面）
                            saveDisasterSeismicInfluence(obj);
                        }

                        return RestResponse.succeed(resultList);
                    }
                }else if(typeCode.contains(FxfzConstants.DSA)){//地震烈度图范围（地震烈度图绘制页面）
                    String xsemId = typeCode.split(",")[1];//当前地震事件id
                    if (!PlatformObjectUtils.isEmpty(xsemId)) {
                        //根据事件ID逻辑删除地震烈度图范围（地震烈度图绘制页面）
                        deleteDrawSeismicInfluence(xsemId);
                        //地震烈度图范围
                        List<DrawSeismicInfluence> resultList = new ArrayList();
                        List<List<Object>> shpList = shpData.getShpList();
                        for (int i = 0; i < shpList.size(); i++) {
                            List<Object> list = shpList.get(i);
                            DrawSeismicInfluence obj = new DrawSeismicInfluence();
                            obj.setGeom(ShpAnalyticUtil.checkGeomTypeOf(list.get(0).toString(), GeomTypeEnum.MULTIPOLYGON));
//                            obj.setArea(BigDecimal.valueOf(ShpAnalyticUtil.getDoubleVal(list.get(4).toString(), "面积", true)));
//                            obj.setIntensity1(ShpAnalyticUtil.getStringVal(list.get(5).toString(), "烈度", true));
//                            obj.setIntensitys(ShpAnalyticUtil.getStringVal(list.get(6).toString(), "烈度", true));
//                            obj.setIntensity(ShpAnalyticUtil.getStringVal(list.get(7).toString(), "烈度", true));
                            obj.setArea(BigDecimal.valueOf(ShpAnalyticUtil.getDoubleVal(list.get(2).toString(), "面积", true)));
                            String intensity1 = ShpAnalyticUtil.getStringVal(list.get(3).toString(), "烈度", false);
                            String intensitys = ShpAnalyticUtil.getStringVal(list.get(4).toString(), "烈度", false);
                            String intensity = ShpAnalyticUtil.getStringVal(list.get(5).toString(), "烈度", true);
                            //罗马数字1-12：1-Ⅰ、2-Ⅱ、3-Ⅲ、4-Ⅳ、5-Ⅴ、6-Ⅵ、7-Ⅶ、8-Ⅷ、9-Ⅸ、10-Ⅹ、11-Ⅺ、12-Ⅻ
                            if(intensity.equals("6")){
                                intensitys = "Ⅵ";
                            }else if(intensity.equals("7")){
                                intensitys = "Ⅶ";
                            }else if(intensity.equals("8")){
                                intensitys = "Ⅷ";
                            }else if(intensity.equals("9")){
                                intensitys = "Ⅸ";
                            }else if(intensity.equals("10")){
                                intensitys = "Ⅹ";
                            }else if(intensity.equals("11")){
                                intensitys = "Ⅺ";
                            }else if(intensity.equals("12")){
                                intensitys = "Ⅻ";
                            }else{
                                //不符合字段要求
                                ShpAnalyticUtil.getStringValDataWarning(intensitys,"烈度");
                            }
                            intensity1 = intensitys + "度（"+intensity+"度）";//VI度(6度)
                            obj.setIntensity1(intensity1);
                            obj.setIntensitys(intensitys);
                            obj.setIntensity(intensity);
                            //用户ID
                            String userID = PlatformSessionContext.getUserID();
                            obj.setSiId(UUIDGenerator.getUUID());
                            obj.setXsemId(xsemId);//事件ID
                            obj.setCreateTime(new Date());
                            obj.setCreateUser(userID);
                            obj.setDelFlag(YNEnum.N.toString());
                            resultList.add(obj);
                            //保存地震烈度图范围（地震烈度图绘制页面）
                            saveDrawSeismicInfluence(obj);
                        }
                        //超图刷新图层
                        hypergraphService.getWorkspaceReload("xzch_draw_seismic_influence");

                        return RestResponse.succeed(resultList);
                    }
                }
            }

            return RestResponse.succeed(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return RestResponse.fail("该数据类别下没有shp数据");
        }
    }

    //根据事件ID查询灾区范围列表（划定评估子区页面）
    @Override
    public List<SeismicInfluence> getSeismicInfluenceList(String xsemId,String geom) {
        String sql = "select *,st_astext(geom) geom from xzch_loss_seismic_influence where xsem_id = ? and del_flag = ?";
        if (!PlatformObjectUtils.isEmpty(geom)) {//查询空间范围是否在1个灾区范围烈度内
            sql += " and ST_Within(st_geomfromtext(?,4490),geom)";
            return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(SeismicInfluence.class),xsemId,YNEnum.N.toString(),geom);
        }else{
            return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(SeismicInfluence.class),xsemId,YNEnum.N.toString());
        }
    }

    //根据事件ID查询灾区范围列表（灾区范围页面）
    @Override
    public List<DisasterSeismicInfluence> getDisasterSeismicInfluenceList(String xsemId,String geom) {
        String sql = "select *,st_astext(geom) geom from xzch_disaster_seismic_influence where xsem_id = ? and del_flag = ?";
        if (!PlatformObjectUtils.isEmpty(geom)) {//查询空间范围是否在1个灾区范围烈度内
            sql += " and ST_Within(st_geomfromtext(?,4490),geom)";
            return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DisasterSeismicInfluence.class),xsemId,YNEnum.N.toString(),geom);
        }else{
            return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DisasterSeismicInfluence.class),xsemId,YNEnum.N.toString());
        }
    }

    //根据事件ID查询灾区范围列表（地震烈度图绘制页面）
    @Override
    public List<DrawSeismicInfluence> getDrawSeismicInfluenceList(String xsemId, String geom) {
        String sql = "select *,st_astext(geom) geom from xzch_draw_seismic_influence where xsem_id = ? and del_flag = ?";
        if (!PlatformObjectUtils.isEmpty(geom)) {//查询空间范围是否在1个灾区范围烈度内
            sql += " and ST_Within(st_geomfromtext(?,4490),geom)";
            return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DrawSeismicInfluence.class),xsemId,YNEnum.N.toString(),geom);
        }else{
            sql += " order by CAST(intensity as int)";
            return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DrawSeismicInfluence.class),xsemId,YNEnum.N.toString());
        }
    }

    @Override
    public List<SurTaskManage> getSurTaskManageList(String xsemId,String geom,String type) {
        StringBuilder sql = new StringBuilder("select *,ST_AsText(geom) geom from xczh_survey_task_manage");
        StringBuilder whereSql = new StringBuilder(" where del_flag = '0'");
        if (!PlatformObjectUtils.isEmpty(xsemId)) {
            whereSql.append(" and xsem_id  = '"+xsemId+"'");
        }
        if (!PlatformObjectUtils.isEmpty(geom)) {//查询空间范围是否在1个灾区范围烈度内
            whereSql.append(" and ST_Within(st_geomfromtext(?,4490),geom) and type= ? ");
            return jdbcTemplate.query(sql.append(whereSql).toString(), new BeanPropertyRowMapper<>(SurTaskManage.class),geom,type);
        }else{
            return jdbcTemplate.query(sql.append(whereSql).toString(), new BeanPropertyRowMapper<>(SurTaskManage.class));
        }
    }

    @Override
    public List<InvestigationTask> getInvTaskManageList(String xsemId, String geom) {
        StringBuilder sql = new StringBuilder("select *,ST_AsText(geom) geom from xczh_investigation_task_manage");
        StringBuilder whereSql = new StringBuilder(" where del_flag = '0'");
        if (!PlatformObjectUtils.isEmpty(xsemId)) {
            whereSql.append(" and xsem_id = '"+xsemId+"'");
        }
        if (!PlatformObjectUtils.isEmpty(geom)) {//查询空间范围是否在1个灾区范围烈度内
            whereSql.append(" and ST_Within(st_geomfromtext(?,4490),geom) ");
            return jdbcTemplate.query(sql.append(whereSql).toString(), new BeanPropertyRowMapper<>(InvestigationTask.class),geom);
        }else{
            return jdbcTemplate.query(sql.append(whereSql).toString(), new BeanPropertyRowMapper<>(InvestigationTask.class));
        }
    }

    //根据事件ID逻辑删除灾区范围（划定评估子区页面）
    public void deleteSeismicInfluence(String xsemId) {
        String sql = "update xzch_loss_seismic_influence set del_flag = ? where xsem_id = ?";
        jdbcTemplate.update(sql, YNEnum.Y.toString(),xsemId);
    }

    //根据事件ID逻辑删除灾区范围（灾区范围页面）
    public void deleteDisasterSeismicInfluence(String xsemId) {
        String sql = "update xzch_disaster_seismic_influence set del_flag = ? where xsem_id = ?";
        jdbcTemplate.update(sql, YNEnum.Y.toString(),xsemId);
    }

    //根据事件ID逻辑删除地震烈度图范围（地震烈度图绘制页面）
    @Override
    public void deleteDrawSeismicInfluence(String xsemId) {
        String sql = "update xzch_draw_seismic_influence set del_flag = ? where xsem_id = ?";
        jdbcTemplate.update(sql, YNEnum.Y.toString(),xsemId);
        //超图刷新图层
//        hypergraphService.getWorkspaceReload("xzch_draw_seismic_influence");
    }

    //根据事件ID、烈度逻辑删除地震烈度图范围（地震烈度图绘制页面）
    @Override
    public void deleteDrawSeismicInfluenceByIntensity(String xsemId, String intensity) {
        String sql = "update xzch_draw_seismic_influence set del_flag = ? where xsem_id = ? and intensity = ?";
        jdbcTemplate.update(sql, YNEnum.Y.toString(), xsemId, intensity);
        //超图刷新图层
//        hypergraphService.getWorkspaceReload("xzch_draw_seismic_influence");
    }

    //根据ID逻辑删除地震烈度图范围（地震烈度图绘制页面）
    @Override
    public void deleteDrawSeismicInfluenceById(String siId) {
        String sql = "update xzch_draw_seismic_influence set del_flag = ? where si_id = ?";
        jdbcTemplate.update(sql, YNEnum.Y.toString(),siId);
        //超图刷新图层
//        hypergraphService.getWorkspaceReload("xzch_draw_seismic_influence");
    }

    //保存灾区范围（划定评估子区页面）
    public void saveSeismicInfluence(SeismicInfluence seismicInfluence) {
        String sql="insert into xzch_loss_seismic_influence(si_id,xsem_id,area,intensity1,intensitys,intensity,del_flag," +
                "create_user,create_time,geom) " +
                "values(:siId, :xsemId, :area, :intensity1, :intensitys, :intensity, :delFlag, :createUser, :createTime," +
                "st_geomfromtext(:geom,4490))";
        SqlParameterSource source = new BeanPropertySqlParameterSource(seismicInfluence);
        namedParameterJdbcTemplate.update(sql, source);
    }

    //保存灾区范围（灾区范围页面）
    public void saveDisasterSeismicInfluence(DisasterSeismicInfluence seismicInfluence) {
        String sql="insert into xzch_disaster_seismic_influence(si_id,xsem_id,area,intensity1,intensitys,intensity,del_flag," +
                "create_user,create_time,geom) " +
                "values(:siId, :xsemId, :area, :intensity1, :intensitys, :intensity, :delFlag, :createUser, :createTime," +
                "st_geomfromtext(:geom,4490))";
        SqlParameterSource source = new BeanPropertySqlParameterSource(seismicInfluence);
        namedParameterJdbcTemplate.update(sql, source);
    }

    //保存地震烈度图范围（地震烈度图绘制页面）
    public void saveDrawSeismicInfluence(DrawSeismicInfluence seismicInfluence) {
        //处理空间数据，判断存在自相交则获取修复后的空间数据，否则返回原空间数据wkt
        seismicInfluence.setGeom(intensityAttenuationService.getGeomValidWkt(seismicInfluence.getGeom()));
        String sql="insert into xzch_draw_seismic_influence(si_id,xsem_id,area,intensity1,intensitys,intensity,del_flag," +
                "create_user,create_time,geom,remark,total_area,coords,curve_coords) " +
                "values(:siId, :xsemId, :area, :intensity1, :intensitys, :intensity, :delFlag, :createUser, :createTime," +
                "st_geomfromtext(:geom,4490),:remark,:totalArea,:coords,:curveCoords)";
        SqlParameterSource source = new BeanPropertySqlParameterSource(seismicInfluence);
        namedParameterJdbcTemplate.update(sql, source);
    }

    //更新地震烈度图范围（地震烈度图绘制页面）
    public void updateDrawSeismicInfluence(DrawSeismicInfluence drawSeismicInfluence) {
        String sql = "update xzch_draw_seismic_influence set geom =st_geomfromtext(:geom,4490),area =:area where si_id =:siId";
        SqlParameterSource source = new BeanPropertySqlParameterSource(drawSeismicInfluence);
        namedParameterJdbcTemplate.update(sql, source);
    }

    //校验包含关系是否正确
    public String checkDrawSeismicInfluence(DrawSeismicInfluence obj) {
        String msg = "校验成功";
        boolean bool = true;
        String xsemId = obj.getXsemId();
        String intensity = obj.getIntensity();
        String siId = obj.getSiId();//已有ID
        if (PlatformObjectUtils.isEmpty(siId)) {
            siId = "";
        }
        String geomText = obj.getGeom();
        if (!PlatformObjectUtils.isEmpty(geomText)) {
            //校验空间数据是否自相交
            String valid = intensityAttenuationService.isGeomValid(geomText);
            if(valid.equals("t")){//正常
                bool = true;
            }else{
                return "空间数据自相交，请重新绘制！";
            }
            System.out.println("校验绘制空间数据是否正常："+bool);
            if(bool){
                //校验低烈度数据是否包含绘制空间数据或不相交
                bool = checkLowerIntensity(xsemId,intensity,geomText);
                System.out.println("校验低烈度数据是否包含绘制空间数据或不相交："+bool);
                if(bool==false){
                    return "绘制等震线的空间数据应该包含在低烈度等震线内！";
                }
            }

            if(bool){
                //校验同烈度数据是否不相交绘制空间数据
                bool = checkSameIntensity(xsemId,intensity,geomText,siId);
                System.out.println("校验同烈度数据是否不相交绘制空间数据："+bool);
                if(bool==false){
                    return "绘制等震线的空间数据不能和其他同烈度的等震线相交！";
                }
            }

            if(bool){
                //校验高烈度数据是否被绘制空间数据包含或不相交
                bool = checkHigherIntensity(xsemId,intensity,geomText);
                System.out.println("校验高烈度数据是否被绘制空间数据包含或不相交："+bool);
                if(bool==false){
                    return "绘制等震线的空间数据应该包含高烈度等震线或不相交！";
                }
            }
        }
        if(bool){
            System.out.println("完成校验绘制空间数据，校验通过");
            msg = "校验成功";
        }

        return msg;
    }

    //校验低烈度数据是否包含绘制空间数据或不相交
    public boolean checkLowerIntensity(String xsemId,String intensity,String geomText) {
        boolean bool = true;
        //查询低烈度数据不符合校验规则的数据数量（低烈度应包含高烈度或不相交）
        String sql ="select count(*) from " +
                "(select si_id,intensity,st_within(st_geomfromtext('"+geomText+"',4490), st_geomfromtext(curve_coords,4490)),st_disjoint(st_geomfromtext('"+geomText+"',4490), st_geomfromtext(curve_coords,4490)) from " +
                "xzch_draw_seismic_influence where xsem_id='"+xsemId+"' and del_flag='0' and CAST(intensity AS int)<'"+intensity+"') a " +
                "where a.st_within='f' and a.st_disjoint='f'";//低烈度不包含高烈度且非不相交
        int count = jdbcTemplate.queryForObject(sql, Integer.class);
        if(count>0){
            bool = false;
        }

        return bool;
    }

    //校验同烈度数据是否不相交绘制空间数据
    public boolean checkSameIntensity(String xsemId,String intensity,String geomText,String siId) {
        boolean bool = true;
        //查询同烈度数据不符合校验规则的数据数量（同烈度应不相交）
        String sql ="select count(*) from " +
                "(select si_id,intensity,st_disjoint(st_geomfromtext('"+geomText+"',4490), st_geomfromtext(curve_coords,4490)) from xzch_draw_seismic_influence " +
                "where xsem_id='"+xsemId+"' and del_flag='0' and intensity='"+intensity+"' and si_id!='"+siId+"') a " +
                "where a.st_disjoint='f'";//同烈度非不相交
        int count = jdbcTemplate.queryForObject(sql, Integer.class);
        if(count>0){
            bool = false;
        }

        return bool;
    }

    //校验高烈度数据是否被绘制空间数据包含或不相交
    public boolean checkHigherIntensity(String xsemId,String intensity,String geomText) {
        boolean bool = true;
        //查询高烈度数据不符合校验规则的数据数量（高烈度应被低烈度包含或不相交）
        String sql ="select count(*) from " +
                "(select si_id,intensity,st_within(st_geomfromtext(curve_coords,4490),st_geomfromtext('"+geomText+"',4490)),st_disjoint(st_geomfromtext('"+geomText+"',4490), st_geomfromtext(curve_coords,4490)) from " +
                "xzch_draw_seismic_influence where xsem_id='"+xsemId+"' and del_flag='0' and CAST(intensity AS int)>'"+intensity+"') a " +
                "where a.st_within='f' and a.st_disjoint='f'";//高烈度不被低烈度包含且非不相交
        int count = jdbcTemplate.queryForObject(sql, Integer.class);
        if(count>0){
            bool = false;
        }

        return bool;
    }

    //根据烈度保存地震烈度图范围（地震烈度图绘制页面）
    @Override
    public String saveDrawSeismicInfluenceByIntensity(DrawSeismicInfluence obj) {
        String xsemId = obj.getXsemId();
        String intensity = obj.getIntensity();
        String siId = obj.getSiId();//已有ID
        obj.setCurveCoords(obj.getGeom());//贝塞尔曲线面wkt（外圈曲线面）
        //校验包含关系是否正确
        String msg = checkDrawSeismicInfluence(obj);
        if(!msg.equals("校验成功")){
            return msg;
        }
        if (!PlatformObjectUtils.isEmpty(siId)) {
            //根据ID逻辑删除地震烈度图范围（地震烈度图绘制页面）
            deleteDrawSeismicInfluenceById(siId);
        }
        //按6度带投影计算空间数据面积
        String area = getAreaByGeomEPSG6(obj.getGeom());
        obj.setArea(BigDecimal.valueOf(Double.valueOf(area)));
        String intensitys = "";
        //罗马数字1-12：1-Ⅰ、2-Ⅱ、3-Ⅲ、4-Ⅳ、5-Ⅴ、6-Ⅵ、7-Ⅶ、8-Ⅷ、9-Ⅸ、10-Ⅹ、11-Ⅺ、12-Ⅻ
        if(intensity.equals("6")){
            intensitys = "Ⅵ";
        }else if(intensity.equals("7")){
            intensitys = "Ⅶ";
        }else if(intensity.equals("8")){
            intensitys = "Ⅷ";
        }else if(intensity.equals("9")){
            intensitys = "Ⅸ";
        }else if(intensity.equals("10")){
            intensitys = "Ⅹ";
        }else if(intensity.equals("11")){
            intensitys = "Ⅺ";
        }
        String intensity1 = intensitys + "度（"+intensity+"度）";//VI度(6度)
        obj.setIntensity1(intensity1);
        obj.setIntensitys(intensitys);
        obj.setIntensity(intensity);
        //用户ID
        String userID = PlatformSessionContext.getUserID();
        obj.setSiId(UUIDGenerator.getUUID());
        obj.setXsemId(xsemId);//事件ID
        obj.setCreateTime(new Date());
        obj.setCreateUser(userID);
        obj.setDelFlag(YNEnum.N.toString());
        //地震烈度图范围（地震烈度图绘制页面）
        saveDrawSeismicInfluence(obj);
        msg = "保存成功";
        //计算全部烈度空间数据及面积（地震烈度图绘制页面）
        countAllDrawSeismicInfluenceGeom(xsemId,true);
        return msg;
    }

    //计算全部烈度空间数据及面积（地震烈度图绘制页面）
    @Override
    public void countAllDrawSeismicInfluenceGeom(String xsemId,boolean bool) {
        //用户ID
        String userID = PlatformSessionContext.getUserID();
        //根据事件ID查询地震烈度图列表（地震烈度图绘制页面）
        List<DrawSeismicInfluence> list = getDrawSeismicInfluenceList(xsemId, null);
        if(list.size()>0){
            for(int i=(list.size()-1);i>=0;i--){
                DrawSeismicInfluence drawSeismicInfluence = list.get(i);
                String intensity = drawSeismicInfluence.getIntensity();
                String geomText = drawSeismicInfluence.getGeom();
                String temp = geomText.replace("MULTIPOLYGON(((","");
                temp = temp.replace(")))","");
                temp = temp.replace("),(","#");
                temp = temp.split("#")[0];//外圈经纬度
                String newGeomText = "MULTIPOLYGON(((" + temp + ")))";
                //查询空间数据减去所有相交的高烈度空间数据
                newGeomText = getAreaDiffrence(xsemId,intensity,newGeomText);
                drawSeismicInfluence.setGeom(newGeomText);
                //按6度带投影计算空间数据面积
                String newArea = getAreaByGeomEPSG6(newGeomText);
                drawSeismicInfluence.setArea(BigDecimal.valueOf(Double.valueOf(newArea)));
                //更新地震烈度图范围（地震烈度图绘制页面）
                updateDrawSeismicInfluence(drawSeismicInfluence);
            }
            //计算各烈度总面积并更新字段
            countTotalAreaByXsemId(xsemId);
        }

        if(bool){
            BizThreadPoolManage.exeBizThreadPoolExecutor.execute(() -> {
                try {
                    //超图刷新图层
                    hypergraphService.getWorkspaceReload("xzch_draw_seismic_influence");
                } catch (Exception e) {
                    log.warn("超图刷新图层失败xzch_draw_seismic_influence");
                    log.error(e.getMessage(), e);
                }
            });
        }
    }

    //查询空间数据减去所有相交的高烈度空间数据
    public String getAreaDiffrence(String xsemId,String intensity,String geomText) {
        //查询高烈度空间数据数量
        String sql0 ="select count(*) from xzch_draw_seismic_influence where del_flag='0' and xsem_id='"+xsemId+"' and CAST(intensity AS int)>"+intensity;
        int count = jdbcTemplate.queryForObject(sql0, Integer.class);
        if(count>0){
            //查询空间数据减去所有相交的高烈度空间数据
            String sql = "select st_astext(st_difference((select st_geomfromtext('"+geomText+"',4490))," +
                    "(select st_union(geom) from xzch_draw_seismic_influence " +
                    "WHERE xsem_id='"+xsemId+"' and del_flag='0' and CAST(intensity AS int)>"+intensity+")))";
            geomText = jdbcTemplate.queryForObject(sql, String.class);
            //处理空间数据，判断存在自相交则获取修复后的空间数据，否则返回原空间数据wkt
            geomText = intensityAttenuationService.getGeomValidWkt(geomText);
        }

        return geomText;
    }

    //按6度带投影计算空间数据面积
    @Override
    public String getAreaByGeomEPSG6(String geomText) {
        //CGCS2000 6度分
        //4502--CGCS2000_GK_CM_75E--中央子午线75E，带号13  72--78
        //4512--CGCS2000_GK_CM_135E--中央子午线135E，带号23  132-138
        String sql = "select st_area(st_transform(st_geomfromtext(?,4490),(floor((st_x(st_centroid(st_geomfromtext(?,4490)))-72)/6)-10+4512)::int4))";

        return jdbcTemplate.queryForObject(sql, String.class, geomText, geomText);
    }

    //按3度带投影计算空间数据面积
    @Override
    public String getAreaByGeomEPSG3(String geomText) {
        //CGCS2000 3度分
        //4534--CGCS2000_3_Degree_GK_CM_75E--中央子午线75E，带号25  73.5--76.5
        //4554--CGCS2000_3_Degree_GK_CM_135E--中央子午线135E，带号45  133.5--136.5
        String sql = "select st_area(st_transform(st_geomfromtext(?,4490),(floor((st_x(st_centroid(st_geomfromtext(?,4490)))-73.5)/3)-20+4554)::int4))";

        return jdbcTemplate.queryForObject(sql, String.class, geomText, geomText);
    }

    @Override
    public List<IntensityMapVo> getDrawSeismicInfluence(String xsemId) {
        String sql = "select *,si_id as id,st_astext(geom) geom from xzch_draw_seismic_influence where xsem_id = ? and del_flag = ?";
        sql += " order by CAST(intensity as int)";

        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(IntensityMapVo.class),xsemId,YNEnum.N.toString());

    }

    //计算各烈度总面积并更新字段
    public void countTotalAreaByXsemId(String xsemId) {
        String sql = "update xzch_draw_seismic_influence set total_area=(select a.total from " +
                "(select intensity,sum(area) as total from xzch_draw_seismic_influence " +
                "where xsem_id='"+xsemId+"' and del_flag='0' " +
                "group by intensity order by CAST(intensity AS int)) a where intensity=xzch_draw_seismic_influence.intensity) " +
                "where xsem_id='"+xsemId+"' and del_flag='0';";
        jdbcTemplate.update(sql);
    }

    /**
     * 统一文件名，提取出临时文件
     *
     * @param fileIds 文件ids，通过”,“拼接
     */
    public Map<String, File> uniformFileName1(String fileIds) throws FileNotFoundException {
        String[] idList = fileIds.split(",");
        String tempFileName = System.currentTimeMillis() + "";
        Map<String, File> fileMap = new HashMap<>();
        for (String attachId : idList) {
            AttachmentInfoEntity attach = attachmentInfoService.getAttach(attachId);
            File targetFile = new File(ResourceUtils.getURL("classpath:").getPath() + File.separator + "cache_file" + File.separator + tempFileName + "." + FileUtil.getSuffix(attach.getAttachName()));
            FileUtil.copy(new File(localDir + File.separator + attach.getAttachPath()), targetFile, true);
            fileMap.put("." + FileUtil.getSuffix(attach.getAttachName()), targetFile);
        }
        return fileMap;
    }

    /**
     * 统一文件名
     *
     * @param fileIds
     */
    private void uniformFileName(String fileIds) {
        String[] idList = fileIds.split(",");
        AttachmentInfoEntity attachRoot = attachmentInfoService.getAttach(idList[0]);
        String attachRootPath = attachRoot.getAttachPath();
        String filePathCurrTime = getFilePathCurrTime(attachRootPath);
        for (int i = 1; i < idList.length; i++) {
            AttachmentInfoEntity attach = attachmentInfoService.getAttach(idList[i]);
            if (getFilePathCurrTime(attach.getAttachPath()).equals(filePathCurrTime)) {
                continue;
            }
            String attachPath = attach.getAttachPath();
            String fileDiskPath = localDir + attachPath;
            String attachName = attach.getAttachName();
            attachName = attachName.substring(0,attachName.lastIndexOf("."));
            String newName = attachName + "_" + filePathCurrTime + "." + FileUtil.getSuffix(attach.getAttachName());
            FileUtil.rename(new File(fileDiskPath), newName, true);
            attach.setAttachPath(attachPath.replace(getFilePathCurrTime(attachPath), filePathCurrTime));
            attachmentInfoService.update(attach);
        }
    }
    private String getNonSuffixFileName(String fileName) {
        return fileName.replaceAll("." + FileUtil.getSuffix(fileName), "");
    }

    private String getFilePathCurrTime(String filePath) {
        return filePath.split("_")[1].replaceAll("." + FileUtil.getSuffix(filePath.split("_")[1]), "");
    }

    /*public ParsingResult getShpData(String fileIds) throws Exception {
        //.prj结尾用来校验是否为2000坐标系
        String prj = "";
        //.cpg文件用来获得编码格式,例如utf-8
        String cpg = "";
        //.shp文件用来获得数据
        String shp = "";
        //根据id获取真实地址
        String[] split = fileIds.split(",");
        for (String id : split) {
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(id);
            String attachPath = attachmentInfoEntity.getAttachPath();
            String substring = attachPath.substring(attachPath.length() - 4);
            if (substring.equals(".prj")) {
                prj = localDir + File.separator + attachPath;
            } else if (substring.equals(".cpg")) {
                cpg = localDir + File.separator + attachPath;
            } else if (substring.equals(".shp")) {
                shp = localDir + File.separator + attachPath;
            }
        }
        return ShpAnalyticUtil.analytic(prj, cpg, shp);
    }*/

    /**
     * 解析shp文件返回shp数据
     *
     * @param fileMap 文件
     * @return
     */
    public ParsingResult getShpData(Map<String, File> fileMap) throws Exception {
        // .prj结尾用来校验是否为2000坐标系
        String prj = fileMap.get(".prj") == null ? StringUtils.EMPTY : fileMap.get(".prj").getPath();
        // .cpg文件用来获得编码格式,例如utf-8
        String cpg = fileMap.get(".cpg") == null ? StringUtils.EMPTY : fileMap.get(".cpg").getPath();
        // .shp文件用来获得数据
        String shp = fileMap.get(".shp") == null ? StringUtils.EMPTY : fileMap.get(".shp").getPath();
        return ShpAnalyticUtil.analytic(prj, cpg, shp);
    }

    //获取字段说明
    @Override
    public RestResponse getFileDesc(String typeCode2) {
        //灾害范围
        Field[] declaredFields = SeismicInfluence.class.getDeclaredFields();
        List<FieldDesc> list = new ArrayList<>();
        AtomicInteger sno = new AtomicInteger(1);
        if(declaredFields.length>0){
            for(Field field : declaredFields){
                FieldDesc fieldDesc = new FieldDesc();
                field.setAccessible(true);
                EntityValue entityValue = field.getAnnotation(EntityValue.class);
                if(entityValue==null){
                    continue;
                }
                String type = entityValue.type();
                String must = entityValue.must();
                String name = entityValue.name();
                String desc = entityValue.desc();
                String fieldName = field.getName();
                fieldDesc.setType(type).setMust(must).setName(name).setDesc(desc).setSno(sno.get());
                sno.getAndAdd(1);
                list.add(fieldDesc);
            }
        }

        return ResponseCreator.createSuccessResponse(list);
    }

    @Override
    public List<String> getCountyByIntensityAndXsemId(String intensity, String xsemId) {
        String sql = "select a.name from district_boundary_county a,(select st_union(geom) as geom from xzch_draw_seismic_influence " +
                "where cast(intensity as int)>='" + intensity + "' and xsem_id='" + xsemId + "' and del_flag='0') b where st_intersects(a.geom, b.geom)";
        List<String> list = jdbcTemplate.queryForList(sql, String.class);
        return list;
    }

    @Override
    public void update(DrawSeismicInfluence drawSeismicInfluence) {
        String sql = "update xzch_draw_seismic_influence set remark =:remark where del_flag='0' and xsem_id = '"+drawSeismicInfluence.getXsemId()+"'";
        SqlParameterSource source = new BeanPropertySqlParameterSource(drawSeismicInfluence);
        namedParameterJdbcTemplate.update(sql, source);
    }

    @Override
    public String getRemark(String xsemId) {
        List<String> list = jdbcTemplate.queryForList("SELECT remark FROM xzch_draw_seismic_influence where del_flag='0'", String.class);
        return list.size()<1?null:list.get(0);
    }

    @Override
    public DrawSeismicInfluence findBySiId(String siId) {
        String sql="select * from xzch_loss_seismic_influence where si_id = '"+siId+"' and del_flag = '0'";
        DrawSeismicInfluence drawSeismicInfluence=new DrawSeismicInfluence();
        try {
            drawSeismicInfluence = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(DrawSeismicInfluence.class));
            return drawSeismicInfluence;
        } catch (Exception e) {
            return null;
        }
    }
}
